package com.service.impl;

import com.dao.ProductDao;
import com.service.ProductService;
import com.service.RedisService;
import core.entity.Product;
import core.es.ProductEs;
import core.vo.ProductVO;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

import static core.Constants.Es.INDEX_NAME;
import static core.Constants.Mq.EXCHANGE_NAME;
import static core.Constants.Mq.ROUTING_KEY;

@Service
public class ProductServiceImpl implements ProductService {
    //搜索命中的字段才高亮，不是此数组中的两个字段都高亮
    public static final String[] ES_SEARCH_FIELDS = {"name", "productDesc"};
    private ProductDao productDao;

    private RabbitTemplate rabbitTemplate;
    private ElasticsearchRestTemplate esTemplate;
    private RedisService redisService;

    public ProductServiceImpl(ProductDao productDao,
                              RabbitTemplate rabbitTemplate,
                              ElasticsearchRestTemplate esTemplate,
                              RedisService redisService) {

        this.productDao = productDao;
        this.rabbitTemplate = rabbitTemplate;
        this.esTemplate = esTemplate;
        this.redisService = redisService;
    }

    @Override
    public void insert(ProductVO productVO) {
        //spring BeanUtils与开源的MapStruct框架
        Product product = new Product();
        product.setProductName(productVO.getName());
        product.setProductDesc(productVO.getDesc());
        product.setProductPrice(productVO.getPrice());
        productDao.insert(product);

        rabbitTemplate.convertAndSend(EXCHANGE_NAME, ROUTING_KEY, product);

    }

    @Override
    public List<ProductEs> searchProductsByEs(String keyword) {
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .field("productDesc")
                .highlighterType("unified")
                .preTags("<span class='hl'>")
                .postTags("</span>");

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(keyword, "name", "desc"))
                .withHighlightBuilder(highlightBuilder)
                .build();

        SearchHits<ProductEs> searchHits = esTemplate
                .search(searchQuery, ProductEs.class, IndexCoordinates.of(INDEX_NAME));

        return searchHits
                .getSearchHits()
                .stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
    }

    @Override
    public Product getById(int id) {
        Product product = null;
        Object cachedProduct = redisService.get("product:" + id);
        if (cachedProduct != null) {
            System.out.println("=====从缓存中取得数据=====");
            product = (Product) cachedProduct;
            return product;
        } else {
            System.out.println("====从缓存中取不到数据=== 从db中取");
            product = productDao.getById(id);
            redisService.setEx("product:" + id, product, 30);
        }
        return product;
    }
}
